{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<i>Copyright (c) Microsoft Corporation. All rights reserved.</i>\n",
    "\n",
    "<i>Licensed under the MIT License.</i>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# xDeepFM : the eXtreme Deep Factorization Machine \n",
    "This notebook will give you a quick example of how to train an [xDeepFM model](https://arxiv.org/abs/1803.05170). \n",
    "xDeepFM \\[1\\] is a deep learning-based model aims at capturing both lower- and higher-order feature interactions for precise recommender systems. Thus it can learn feature interactions more effectively and manual feature engineering effort can be substantially reduced. To summarize, xDeepFM has the following key properties:\n",
    "* It contains a component, named CIN, that learns feature interactions in an explicit fashion and in vector-wise level;\n",
    "* It contains a traditional DNN component that learns feature interactions in an implicit fashion and in bit-wise level.\n",
    "* The implementation makes this model quite configurable. We can enable different subsets of components by setting hyperparameters like `use_Linear_part`, `use_FM_part`, `use_CIN_part`, and `use_DNN_part`. For example, by enabling only the `use_Linear_part` and `use_FM_part`, we can get a classical FM model.\n",
    "\n",
    "In this notebook, we test xDeepFM on two datasets: 1) a small synthetic dataset and 2) [Criteo dataset](http://labs.criteo.com/category/dataset)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 0. Global Settings and Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "System version: 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34) \n",
      "[GCC 7.3.0]\n",
      "Tensorflow version: 1.12.0\n"
     ]
    }
   ],
   "source": [
    "import sys\n",
    "sys.path.append(\"../../\")\n",
    "import os\n",
    "import papermill as pm\n",
    "from tempfile import TemporaryDirectory\n",
    "\n",
    "import tensorflow as tf\n",
    "\n",
    "from reco_utils.common.constants import SEED\n",
    "from reco_utils.recommender.deeprec.deeprec_utils import (\n",
    "    download_deeprec_resources, prepare_hparams\n",
    ")\n",
    "from reco_utils.recommender.deeprec.models.xDeepFM import XDeepFMModel\n",
    "from reco_utils.recommender.deeprec.IO.iterator import FFMTextIterator\n",
    "\n",
    "print(\"System version: {}\".format(sys.version))\n",
    "print(\"Tensorflow version: {}\".format(tf.__version__))\n",
    "\n",
    "tmpdir = TemporaryDirectory()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "tags": [
     "parameters"
    ]
   },
   "outputs": [],
   "source": [
    "EPOCHS_FOR_SYNTHETIC_RUN = 15\n",
    "EPOCHS_FOR_CRITEO_RUN = 30\n",
    "BATCH_SIZE_SYNTHETIC = 128\n",
    "BATCH_SIZE_CRITEO = 4096\n",
    "RANDOM_SEED = SEED  # Set None for non-deterministic result"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "xDeepFM uses the FFM format as data input: `<label> <field_id>:<feature_id>:<feature_value>`  \n",
    "Each line represents an instance, `<label>` is a binary value with 1 meaning positive instance and 0 meaning negative instance. \n",
    "Features are divided into fields. For example, user's gender is a field, it contains three possible values, i.e. male, female and unknown. Occupation can be another field, which contains many more possible values than the gender field. Both field index and feature index are starting from 1. <br>\n",
    "\n",
    "## 1. Synthetic data\n",
    "Now let's start with a small synthetic dataset. In this dataset, there are 10 fields, 1000 fefatures, and label is generated according to the result of a set of preset pair-wise feature interactions. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "10.6MB [00:00, 31.2MB/s]                            \n"
     ]
    }
   ],
   "source": [
    "data_path = tmpdir.name\n",
    "yaml_file = os.path.join(data_path, r'xDeepFM.yaml')\n",
    "train_file = os.path.join(data_path, r'synthetic_part_0')\n",
    "valid_file = os.path.join(data_path, r'synthetic_part_1')\n",
    "test_file = os.path.join(data_path, r'synthetic_part_2')\n",
    "output_file = os.path.join(data_path, r'output.txt')\n",
    "\n",
    "if not os.path.exists(yaml_file):\n",
    "    download_deeprec_resources(r'https://recodatasets.blob.core.windows.net/deeprec/', data_path, 'xdeepfmresources.zip')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.1 Prepare hyper-parameters\n",
    "prepare_hparams() will create a full set of hyper-parameters for model training, such as learning rate, feature number, and dropout ratio. We can put those parameters in a yaml file, or pass parameters as the function's parameters (which will overwrite yaml settings)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('DNN_FIELD_NUM', None), ('FEATURE_COUNT', 1000), ('FIELD_COUNT', 10), ('MODEL_DIR', None), ('PAIR_NUM', None), ('SUMMARIES_DIR', None), ('activation', ['relu', 'relu']), ('attention_activation', None), ('attention_dropout', 0.0), ('attention_layer_sizes', None), ('batch_size', 128), ('cross_activation', 'identity'), ('cross_l1', 0.0), ('cross_l2', 0.0001), ('cross_layer_sizes', [1]), ('cross_layers', None), ('data_format', 'ffm'), ('dim', 10), ('doc_size', None), ('dropout', [0.0, 0.0]), ('dtype', 32), ('embed_l1', 0.0), ('embed_l2', 0.0001), ('enable_BN', False), ('entityEmb_file', None), ('entity_dim', None), ('entity_embedding_method', None), ('entity_size', None), ('epochs', 15), ('fast_CIN_d', 0), ('filter_sizes', None), ('init_method', 'tnormal'), ('init_value', 0.3), ('is_clip_norm', 0), ('iterator_type', None), ('kg_file', None), ('kg_training_interval', 5), ('layer_l1', 0.0), ('layer_l2', 0.0001), ('layer_sizes', [100, 100]), ('learning_rate', 0.001), ('load_model_name', 'you model path'), ('load_saved_model', False), ('loss', 'log_loss'), ('lr_kg', 0.5), ('lr_rs', 1), ('max_grad_norm', 2), ('method', 'classification'), ('metrics', ['auc', 'logloss']), ('model_type', 'xDeepFM'), ('mu', None), ('n_item', None), ('n_item_attr', None), ('n_user', None), ('n_user_attr', None), ('num_filters', None), ('optimizer', 'adam'), ('reg_kg', 0.0), ('save_epoch', 2), ('save_model', False), ('show_step', 200000), ('train_ratio', None), ('transform', None), ('use_CIN_part', True), ('use_DNN_part', False), ('use_FM_part', False), ('use_Linear_part', False), ('user_clicks', None), ('user_dropout', False), ('wordEmb_file', None), ('word_size', None), ('write_tfevents', False)]\n"
     ]
    }
   ],
   "source": [
    "hparams = prepare_hparams(yaml_file, \n",
    "                          FEATURE_COUNT=1000, \n",
    "                          FIELD_COUNT=10, \n",
    "                          cross_l2=0.0001, \n",
    "                          embed_l2=0.0001, \n",
    "                          learning_rate=0.001, \n",
    "                          epochs=EPOCHS_FOR_SYNTHETIC_RUN,\n",
    "                          batch_size=BATCH_SIZE_SYNTHETIC)\n",
    "print(hparams)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.2 Create data loader\n",
    "Designate a data iterator for the model. xDeepFM uses FFMTextIterator. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_creator = FFMTextIterator"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.3 Create model\n",
    "When both hyper-parameters and data iterator are ready, we can create a model:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Add CIN part.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/data/anaconda/envs/reco_gpu/lib/python3.6/site-packages/tensorflow/python/ops/gradients_impl.py:112: UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory.\n",
      "  \"Converting sparse IndexedSlices to a dense Tensor of unknown shape. \"\n"
     ]
    }
   ],
   "source": [
    "model = XDeepFMModel(hparams, input_creator, seed=RANDOM_SEED)\n",
    "\n",
    "## sometimes we don't want to train a model from scratch\n",
    "## then we can load a pre-trained model like this: \n",
    "#model.load_model(r'your_model_path')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's see what is the model's performance at this point (without starting training):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'auc': 0.5043, 'logloss': 0.7515}\n"
     ]
    }
   ],
   "source": [
    "print(model.run_eval(test_file))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "AUC=0.5 is a state of random guess. We can see that before training, the model behaves like random guessing.\n",
    "\n",
    "#### 1.4 Train model\n",
    "Next we want to train the model on a training set, and check the performance on a validation dataset. Training the model is as simple as a function call:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "at epoch 1 train info: auc:0.5189, logloss:0.7006 eval info: auc:0.504, logloss:0.7042\n",
      "at epoch 1 , train time: 3.0 eval time: 3.1\n",
      "at epoch 2 train info: auc:0.5365, logloss:0.6919 eval info: auc:0.5066, logloss:0.6973\n",
      "at epoch 2 , train time: 2.7 eval time: 3.1\n",
      "at epoch 3 train info: auc:0.5552, logloss:0.6884 eval info: auc:0.5099, logloss:0.6953\n",
      "at epoch 3 , train time: 2.8 eval time: 3.1\n",
      "at epoch 4 train info: auc:0.5784, logloss:0.6848 eval info: auc:0.5147, logloss:0.6946\n",
      "at epoch 4 , train time: 2.9 eval time: 3.1\n",
      "at epoch 5 train info: auc:0.6104, logloss:0.6783 eval info: auc:0.523, logloss:0.6941\n",
      "at epoch 5 , train time: 2.7 eval time: 3.2\n",
      "at epoch 6 train info: auc:0.6582, logloss:0.6625 eval info: auc:0.5416, logloss:0.6929\n",
      "at epoch 6 , train time: 2.7 eval time: 3.1\n",
      "at epoch 7 train info: auc:0.7318, logloss:0.6204 eval info: auc:0.5916, logloss:0.6831\n",
      "at epoch 7 , train time: 2.8 eval time: 3.1\n",
      "at epoch 8 train info: auc:0.83, logloss:0.5231 eval info: auc:0.7024, logloss:0.6288\n",
      "at epoch 8 , train time: 2.7 eval time: 3.2\n",
      "at epoch 9 train info: auc:0.907, logloss:0.3992 eval info: auc:0.8154, logloss:0.5257\n",
      "at epoch 9 , train time: 2.7 eval time: 3.1\n",
      "at epoch 10 train info: auc:0.9501, logloss:0.2976 eval info: auc:0.8826, logloss:0.4315\n",
      "at epoch 10 , train time: 2.8 eval time: 3.1\n",
      "at epoch 11 train info: auc:0.9733, logloss:0.2211 eval info: auc:0.9205, logloss:0.3605\n",
      "at epoch 11 , train time: 2.7 eval time: 3.2\n",
      "at epoch 12 train info: auc:0.9859, logloss:0.1636 eval info: auc:0.9431, logloss:0.3082\n",
      "at epoch 12 , train time: 2.7 eval time: 3.1\n",
      "at epoch 13 train info: auc:0.9929, logloss:0.1196 eval info: auc:0.9577, logloss:0.2682\n",
      "at epoch 13 , train time: 2.8 eval time: 3.1\n",
      "at epoch 14 train info: auc:0.9967, logloss:0.0859 eval info: auc:0.9676, logloss:0.2369\n",
      "at epoch 14 , train time: 2.7 eval time: 3.2\n",
      "at epoch 15 train info: auc:0.9986, logloss:0.0605 eval info: auc:0.9745, logloss:0.2128\n",
      "at epoch 15 , train time: 2.7 eval time: 3.1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<reco_utils.recommender.deeprec.models.xDeepFM.XDeepFMModel at 0x7fb24448dba8>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.fit(train_file, valid_file)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.5 Evaluate model\n",
    "\n",
    "Again, let's see what is the model's performance now (after training):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'auc': 0.9716, 'logloss': 0.2278}\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/data/anaconda/envs/reco_gpu/lib/python3.6/site-packages/ipykernel_launcher.py:3: DeprecationWarning: Function record is deprecated and will be removed in verison 1.0.0 (current version 0.19.0). Please see `scrapbook.glue` (nteract-scrapbook) as a replacement for this functionality.\n",
      "  This is separate from the ipykernel package so we can avoid doing imports until\n"
     ]
    },
    {
     "data": {
      "application/papermill.record+json": {
       "res_syn": {
        "auc": 0.9716,
        "logloss": 0.2278
       }
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "res_syn = model.run_eval(test_file)\n",
    "print(res_syn)\n",
    "pm.record(\"res_syn\", res_syn)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we want to get the full prediction scores rather than evaluation metrics, we can do this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<reco_utils.recommender.deeprec.models.xDeepFM.XDeepFMModel at 0x7fb24448dba8>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.predict(test_file, output_file)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Criteo data \n",
    "\n",
    "Now we have successfully launched an experiment on a synthetic dataset. Next let's try something on a real world dataset, which is a small sample from [Criteo dataset](http://labs.criteo.com/category/dataset). Criteo dataset is a well known industry benchmarking dataset for developing CTR prediction models and it's frequently adopted as evaluation dataset by research papers. The original dataset is too large for a lightweight demo, so we sample a small portion from it as a demo dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "demo with Criteo dataset\n"
     ]
    }
   ],
   "source": [
    "print('demo with Criteo dataset')\n",
    "hparams = prepare_hparams(yaml_file, \n",
    "                          FEATURE_COUNT=2300000, \n",
    "                          FIELD_COUNT=39, \n",
    "                          cross_l2=0.01, \n",
    "                          embed_l2=0.01, \n",
    "                          layer_l2=0.01,\n",
    "                          learning_rate=0.002, \n",
    "                          batch_size=BATCH_SIZE_CRITEO, \n",
    "                          epochs=EPOCHS_FOR_CRITEO_RUN, \n",
    "                          cross_layer_sizes=[20, 10], \n",
    "                          init_value=0.1, \n",
    "                          layer_sizes=[20,20],\n",
    "                          use_Linear_part=True, \n",
    "                          use_CIN_part=True, \n",
    "                          use_DNN_part=True)\n",
    "\n",
    "train_file = os.path.join(data_path, r'cretio_tiny_train')\n",
    "valid_file = os.path.join(data_path, r'cretio_tiny_valid')\n",
    "test_file = os.path.join(data_path, r'cretio_tiny_test')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Add linear part.\n",
      "Add CIN part.\n",
      "Add DNN part.\n",
      "{'auc': 0.4728, 'logloss': 0.7113}\n",
      "at epoch 1 train info: auc:0.6648, logloss:0.5347 eval info: auc:0.6637, logloss:0.5342\n",
      "at epoch 1 , train time: 27.9 eval time: 22.5\n",
      "at epoch 2 train info: auc:0.7155, logloss:0.51 eval info: auc:0.7137, logloss:0.5109\n",
      "at epoch 2 , train time: 24.3 eval time: 22.5\n",
      "at epoch 3 train info: auc:0.7331, logloss:0.5012 eval info: auc:0.7283, logloss:0.5037\n",
      "at epoch 3 , train time: 24.3 eval time: 22.2\n",
      "at epoch 4 train info: auc:0.7412, logloss:0.4964 eval info: auc:0.7359, logloss:0.4991\n",
      "at epoch 4 , train time: 24.1 eval time: 22.3\n",
      "at epoch 5 train info: auc:0.7456, logloss:0.4937 eval info: auc:0.74, logloss:0.4963\n",
      "at epoch 5 , train time: 24.1 eval time: 22.5\n",
      "at epoch 6 train info: auc:0.7487, logloss:0.4919 eval info: auc:0.7426, logloss:0.4946\n",
      "at epoch 6 , train time: 24.1 eval time: 22.3\n",
      "at epoch 7 train info: auc:0.7505, logloss:0.4907 eval info: auc:0.7441, logloss:0.4934\n",
      "at epoch 7 , train time: 24.2 eval time: 22.3\n",
      "at epoch 8 train info: auc:0.7521, logloss:0.4897 eval info: auc:0.7453, logloss:0.4925\n",
      "at epoch 8 , train time: 24.3 eval time: 22.4\n",
      "at epoch 9 train info: auc:0.7534, logloss:0.4887 eval info: auc:0.7462, logloss:0.4917\n",
      "at epoch 9 , train time: 24.2 eval time: 22.3\n",
      "at epoch 10 train info: auc:0.7547, logloss:0.4877 eval info: auc:0.747, logloss:0.491\n",
      "at epoch 10 , train time: 24.0 eval time: 22.5\n",
      "at epoch 11 train info: auc:0.7559, logloss:0.4869 eval info: auc:0.7476, logloss:0.4904\n",
      "at epoch 11 , train time: 24.1 eval time: 22.6\n",
      "at epoch 12 train info: auc:0.7569, logloss:0.4861 eval info: auc:0.7482, logloss:0.49\n",
      "at epoch 12 , train time: 24.1 eval time: 22.4\n",
      "at epoch 13 train info: auc:0.7579, logloss:0.4855 eval info: auc:0.7487, logloss:0.4897\n",
      "at epoch 13 , train time: 24.2 eval time: 22.3\n",
      "at epoch 14 train info: auc:0.7589, logloss:0.4848 eval info: auc:0.7493, logloss:0.4893\n",
      "at epoch 14 , train time: 24.3 eval time: 22.5\n",
      "at epoch 15 train info: auc:0.7601, logloss:0.4841 eval info: auc:0.7498, logloss:0.4889\n",
      "at epoch 15 , train time: 24.2 eval time: 22.3\n",
      "at epoch 16 train info: auc:0.7614, logloss:0.4832 eval info: auc:0.7505, logloss:0.4884\n",
      "at epoch 16 , train time: 24.2 eval time: 22.5\n",
      "at epoch 17 train info: auc:0.763, logloss:0.4822 eval info: auc:0.7512, logloss:0.4879\n",
      "at epoch 17 , train time: 24.3 eval time: 22.6\n",
      "at epoch 18 train info: auc:0.7649, logloss:0.481 eval info: auc:0.752, logloss:0.4874\n",
      "at epoch 18 , train time: 24.0 eval time: 22.4\n",
      "at epoch 19 train info: auc:0.767, logloss:0.4795 eval info: auc:0.7528, logloss:0.4867\n",
      "at epoch 19 , train time: 24.2 eval time: 22.5\n",
      "at epoch 20 train info: auc:0.7695, logloss:0.4779 eval info: auc:0.7537, logloss:0.4861\n",
      "at epoch 20 , train time: 24.2 eval time: 22.4\n",
      "at epoch 21 train info: auc:0.7722, logloss:0.4761 eval info: auc:0.7546, logloss:0.4855\n",
      "at epoch 21 , train time: 24.1 eval time: 22.3\n",
      "at epoch 22 train info: auc:0.7751, logloss:0.4742 eval info: auc:0.7554, logloss:0.4849\n",
      "at epoch 22 , train time: 24.1 eval time: 22.4\n",
      "at epoch 23 train info: auc:0.778, logloss:0.4721 eval info: auc:0.7561, logloss:0.4843\n",
      "at epoch 23 , train time: 24.1 eval time: 22.6\n",
      "at epoch 24 train info: auc:0.7811, logloss:0.47 eval info: auc:0.7568, logloss:0.4838\n",
      "at epoch 24 , train time: 24.1 eval time: 22.5\n",
      "at epoch 25 train info: auc:0.7843, logloss:0.4678 eval info: auc:0.7574, logloss:0.4833\n",
      "at epoch 25 , train time: 24.2 eval time: 22.4\n",
      "at epoch 26 train info: auc:0.7875, logloss:0.4655 eval info: auc:0.7579, logloss:0.4829\n",
      "at epoch 26 , train time: 24.4 eval time: 22.5\n",
      "at epoch 27 train info: auc:0.7909, logloss:0.4631 eval info: auc:0.7583, logloss:0.4825\n",
      "at epoch 27 , train time: 24.1 eval time: 22.4\n",
      "at epoch 28 train info: auc:0.7944, logloss:0.4605 eval info: auc:0.7587, logloss:0.4821\n",
      "at epoch 28 , train time: 24.1 eval time: 22.4\n",
      "at epoch 29 train info: auc:0.7981, logloss:0.4578 eval info: auc:0.759, logloss:0.4818\n",
      "at epoch 29 , train time: 24.2 eval time: 22.6\n",
      "at epoch 30 train info: auc:0.802, logloss:0.4548 eval info: auc:0.7592, logloss:0.4816\n",
      "at epoch 30 , train time: 24.0 eval time: 22.5\n",
      "{'auc': 0.749, 'logloss': 0.4926}\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/data/anaconda/envs/reco_gpu/lib/python3.6/site-packages/ipykernel_launcher.py:9: DeprecationWarning: Function record is deprecated and will be removed in verison 1.0.0 (current version 0.19.0). Please see `scrapbook.glue` (nteract-scrapbook) as a replacement for this functionality.\n",
      "  if __name__ == '__main__':\n"
     ]
    },
    {
     "data": {
      "application/papermill.record+json": {
       "res_real": {
        "auc": 0.749,
        "logloss": 0.4926
       }
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "model = XDeepFMModel(hparams, FFMTextIterator, seed=RANDOM_SEED)\n",
    "\n",
    "# check the predictive performance before the model is trained\n",
    "print(model.run_eval(test_file)) \n",
    "model.fit(train_file, valid_file)\n",
    "# check the predictive performance after the model is trained\n",
    "res_real = model.run_eval(test_file)\n",
    "print(res_real)\n",
    "pm.record(\"res_real\", res_real)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reference\n",
    "\\[1\\] Lian, J., Zhou, X., Zhang, F., Chen, Z., Xie, X., & Sun, G. (2018). xDeepFM: Combining Explicit and Implicit Feature Interactions for Recommender Systems. Proceedings of the 24th ACM SIGKDD International Conference on Knowledge Discovery \\& Data Mining, KDD 2018, London, UK, August 19-23, 2018.<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Cleanup\n",
    "tmpdir.cleanup()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "reco_gpu",
   "language": "python",
   "name": "reco_gpu"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
